package com.app.oral.controller

import com.app.oral.config.ApiResponse
import com.app.oral.dto.*
import com.app.oral.model.ExerciseMode
import com.app.oral.model.ExerciseRecord
import com.app.oral.service.ExerciseRecordService
import com.app.oral.service.UserSessionService
import com.app.oral.service.ExamPaperService
import com.app.oral.util.TeacherPermissionHelper
import jakarta.servlet.http.HttpServletRequest
import org.slf4j.LoggerFactory
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
import io.swagger.v3.oas.annotations.responses.ApiResponse as SwaggerApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.security.SecurityRequirement
import io.swagger.v3.oas.annotations.tags.Tag
import java.math.BigDecimal

/**
 * 练习记录控制器
 */
@RestController
@RequestMapping("/api/v1/exercise-records")
@Tag(name = "练习记录管理", description = "学生练习记录、测试记录相关接口")
class ExerciseRecordController(
    private val exerciseRecordService: ExerciseRecordService,
    private val userSessionService: UserSessionService,
    private val examPaperService: ExamPaperService,
    private val teacherPermissionHelper: TeacherPermissionHelper
) {

    companion object {
        private val logger = LoggerFactory.getLogger(ExerciseRecordController::class.java)
    }

    /**
     * 1. 开始练习/测试 - 创建或获取练习记录
     */
    @Operation(
        summary = "开始练习/测试",
        description = "创建或获取练习记录，支持练习和测试两种模式"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "获取成功"),
        SwaggerApiResponse(responseCode = "400", description = "重复测试或参数错误"),
        SwaggerApiResponse(responseCode = "401", description = "会话无效")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @PostMapping("/start")
    fun startExercise(
        @RequestBody request: StartExerciseRequest,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseProgressResponse>> {
        logger.info("开始练习/测试: paperId={}, mode={}", request.paperId, request.mode)

        val userId = getUserId(httpRequest)

        // 测试模式检查是否已存在记录
        if (request.mode == ExerciseMode.TEST) {
            val existingRecord = exerciseRecordService.findByUserPaperMode(
                userId, request.paperId, ExerciseMode.TEST
            )
            if (existingRecord != null) {
                // 如果已存在测试记录，返回该记录而不是报错
                val response = buildProgressResponse(existingRecord)
                return ResponseEntity.ok(ApiResponse.ok("获取已完成的测试记录", response))
            }
        }

        val record = exerciseRecordService.createOrGet(userId, request.paperId, request.mode)
        val response = buildProgressResponse(record)

        return ResponseEntity.ok(ApiResponse.ok("获取练习记录成功", response))
    }

    /**
     * 1. 查询用户练习进度
     */
    @Operation(
        summary = "查询练习进度",
        description = "根据练习记录ID查询用户的练习进度信息"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "查询成功"),
        SwaggerApiResponse(responseCode = "403", description = "无权访问"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @GetMapping("/{recordId}/progress")
    fun getExerciseProgress(
        @PathVariable recordId: String,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseProgressResponse>> {
        logger.info("查询练习进度: recordId={}", recordId)

        val userId = getUserId(httpRequest)
        val record = exerciseRecordService.findById(recordId)
            ?: return ResponseEntity.notFound().build()

        // 验证记录所有权
        if (record.userId != userId) {
            return ResponseEntity.status(403).body(
                ApiResponse.error("无权访问此练习记录")
            )
        }

        val response = buildProgressResponse(record)

        return ResponseEntity.ok(ApiResponse.ok("查询进度成功", response))
    }

    /**
     * 2.1 更新短文朗读记录（仅练习模式）
     */
    @Operation(
        summary = "更新短文朗读记录",
        description = "更新练习记录中的短文朗读部分（仅练习模式支持）"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "更新成功"),
        SwaggerApiResponse(responseCode = "400", description = "仅练习模式支持"),
        SwaggerApiResponse(responseCode = "403", description = "无权访问"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @PutMapping("/reading")
    fun updateReading(
        @RequestBody request: UpdateReadingRequest,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseProgressResponse>> {
        logger.info("更新短文朗读记录: recordId={}", request.recordId)

        val userId = getUserId(httpRequest)

        // 验证记录权限和模式
        val (_, errorResponse) = validatePracticeRecordAccessWithResponse(request.recordId, userId)
        if (errorResponse != null) return errorResponse

        val updatedRecord = exerciseRecordService.updateReadingResult(
            request.recordId,
            request.audioFileId,
            request.scoreDetails.toModel()
        ) ?: return ResponseEntity.notFound().build()

        val response = buildProgressResponse(updatedRecord)

        return ResponseEntity.ok(ApiResponse.ok("短文朗读记录更新成功", response))
    }

    /**
     * 2.2 更新视听应答记录（仅练习模式）
     */
    @Operation(
        summary = "更新视听应答记录",
        description = "更新练习记录中的视听应答部分（仅练习模式支持）"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "更新成功"),
        SwaggerApiResponse(responseCode = "400", description = "仅练习模式支持或参数错误"),
        SwaggerApiResponse(responseCode = "403", description = "无权访问"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @PutMapping("/listening")
    fun updateListening(
        @RequestBody request: UpdateListeningRequest,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseProgressResponse>> {
        logger.info("更新视听应答记录: recordId={}, index={}", request.recordId, request.listeningIndex)

        val userId = getUserId(httpRequest)

        // 验证记录权限和模式
        val (_, errorResponse) = validatePracticeRecordAccessWithResponse(request.recordId, userId)
        if (errorResponse != null) return errorResponse

        if (request.listeningIndex !in 1..5) {
            return ResponseEntity.badRequest().body(
                ApiResponse.error("视听应答索引必须在1-5之间")
            )
        }

        val updatedRecord = exerciseRecordService.updateListeningResult(
            request.recordId,
            request.listeningIndex,
            request.audioFileId,
            request.score
        ) ?: return ResponseEntity.notFound().build()

        val response = buildProgressResponse(updatedRecord)

        return ResponseEntity.ok(ApiResponse.ok("视听应答记录更新成功", response))
    }

    /**
     * 2.3 更新情景问答记录（仅练习模式）
     */
    @Operation(
        summary = "更新情景问答记录",
        description = "更新练习记录中的情景问答部分（仅练习模式支持）"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "更新成功"),
        SwaggerApiResponse(responseCode = "400", description = "仅练习模式支持或参数错误"),
        SwaggerApiResponse(responseCode = "403", description = "无权访问"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @PutMapping("/dialogue")
    fun updateDialogue(
        @RequestBody request: UpdateDialogueRequest,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseProgressResponse>> {
        logger.info("更新情景问答记录: recordId={}, index={}", request.recordId, request.dialogueIndex)

        val userId = getUserId(httpRequest)

        // 验证记录权限和模式
        val (_, errorResponse) = validatePracticeRecordAccessWithResponse(request.recordId, userId)
        if (errorResponse != null) return errorResponse

        if (request.dialogueIndex !in 1..5) {
            return ResponseEntity.badRequest().body(
                ApiResponse.error("对话索引必须在1-5之间")
            )
        }

        val updatedRecord = exerciseRecordService.updateDialogueResult(
            request.recordId,
            request.dialogueIndex,
            request.audioFileId,
            request.score
        ) ?: return ResponseEntity.notFound().build()

        val response = buildProgressResponse(updatedRecord)

        return ResponseEntity.ok(ApiResponse.ok("情景问答记录更新成功", response))
    }

    /**
     * 2.3 更新话题简述记录（仅练习模式）
     */
    @Operation(
        summary = "更新话题简述记录",
        description = "更新练习记录中的话题简述部分（仅练习模式支持）"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "更新成功"),
        SwaggerApiResponse(responseCode = "400", description = "仅练习模式支持"),
        SwaggerApiResponse(responseCode = "403", description = "无权访问"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @PutMapping("/expression")
    fun updateExpression(
        @RequestBody request: UpdateExpressionRequest,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseProgressResponse>> {
        logger.info("更新话题简述记录: recordId={}", request.recordId)

        val userId = getUserId(httpRequest)

        // 验证记录权限和模式
        val (_, errorResponse) = validatePracticeRecordAccessWithResponse(request.recordId, userId)
        if (errorResponse != null) return errorResponse

        val updatedRecord = exerciseRecordService.updateExpressionResult(
            request.recordId,
            request.audioFileId,
            request.score,
            request.scoreDetails.toModel()
        ) ?: return ResponseEntity.notFound().build()

        val response = buildProgressResponse(updatedRecord)

        return ResponseEntity.ok(ApiResponse.ok("话题简述记录更新成功", response))
    }

    /**
     * 2.4 修改话题简述分数
     */
    @Operation(
        summary = "修改话题简述分数",
        description = "修改练习记录中的话题简述分数和评分详情，不影响音频文件"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "修改成功"),
        SwaggerApiResponse(responseCode = "400", description = "话题简述答案不存在"),
        SwaggerApiResponse(responseCode = "403", description = "无权访问"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @PatchMapping("/expression/score")
    fun updateExpressionScore(
        @RequestBody request: UpdateExpressionScoreRequest,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseProgressResponse>> {
        logger.info("修改话题简述分数: recordId={}, score={}", request.recordId, request.score)

        val userId = getUserId(httpRequest)
        val record = exerciseRecordService.findById(request.recordId)
            ?: return ResponseEntity.notFound().build()

        // 验证记录所有权
        if (record.userId != userId) {
            return ResponseEntity.status(403).body(
                ApiResponse.error("无权访问此练习记录")
            )
        }

        return try {
            val updatedRecord = exerciseRecordService.updateExpressionScore(
                request.recordId,
                request.score,
                request.scoreDetails.toModel()
            ) ?: return ResponseEntity.notFound().build()

            val response = buildProgressResponse(updatedRecord)
            ResponseEntity.ok(ApiResponse.ok("话题简述分数修改成功", response))
        } catch (e: IllegalStateException) {
            ResponseEntity.badRequest().body(
                ApiResponse.error(e.message ?: "话题简述答案不存在")
            )
        }
    }

    /**
     * 3. 一次性提交测试记录（仅测试模式）
     */
    @Operation(
        summary = "提交测试记录",
        description = "一次性提交完整的测试记录（仅测试模式）"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "提交成功"),
        SwaggerApiResponse(responseCode = "400", description = "重复测试或参数错误"),
        SwaggerApiResponse(responseCode = "401", description = "会话无效")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @PostMapping("/submit-test")
    fun submitTest(
        @RequestBody request: SubmitTestRequest,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseRecordDetailResponse>> {
        logger.info("一次性提交测试记录: paperId={}", request.paperId)

        val userId = getUserId(httpRequest)

        // 检查是否已存在测试记录
        val existingRecord = exerciseRecordService.findByUserPaperMode(
            userId, request.paperId, ExerciseMode.TEST
        )
        if (existingRecord != null) {
            return ResponseEntity.badRequest().body(
                ApiResponse.error("该试卷已完成测试，不允许重复测试")
            )
        }

        // 创建并完成测试记录
        val record = exerciseRecordService.createOrGet(userId, request.paperId, ExerciseMode.TEST)

        // 更新短文朗读
        var updatedRecord = exerciseRecordService.updateReadingResult(
            record.id,
            request.reading.audioFileId,
            request.reading.scoreDetails.toModel()
        )!!

        // 更新视听应答
        request.listeningAnswers.sortedBy { it.number }.forEach { ans ->
            updatedRecord = exerciseRecordService.updateListeningResult(
                updatedRecord.id, ans.number, ans.audioFileId, ans.score
            )!!
        }

        // 更新情景问答
        request.dialogueAnswers.sortedBy { it.number }.forEach { ans ->
            updatedRecord = exerciseRecordService.updateDialogueResult(
                updatedRecord.id, ans.number, ans.audioFileId, ans.score
            )!!
        }

        // 更新话题简述并完成记录
        updatedRecord = exerciseRecordService.updateExpressionResult(
            updatedRecord.id,
            request.expression.audioFileId,
            request.expression.score,
            request.expression.scoreDetails.toModel()
        )!!

        val response = buildDetailResponse(updatedRecord)
        return ResponseEntity.ok(ApiResponse.ok("测试记录提交成功", response))
    }

    /**
     * 4. 查询完整的练习记录
     */
    @Operation(
        summary = "查询练习记录详情",
        description = "根据记录ID查询完整的练习记录详细信息"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "查询成功"),
        SwaggerApiResponse(responseCode = "403", description = "无权访问"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @GetMapping("/{recordId}")
    fun getExerciseRecord(
        @PathVariable recordId: String,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseRecordDetailResponse>> {
        logger.info("查询完整练习记录: recordId={}", recordId)

//        val userId = getUserId(httpRequest)
        val record = exerciseRecordService.findById(recordId)
            ?: return ResponseEntity.notFound().build()

//        // 验证记录所有权
//        if (record.userId != userId) {
//            return ResponseEntity.status(403).body(
//                ApiResponse.error("无权访问此练习记录")
//            )
//        }

        val response = buildDetailResponse(record)
        return ResponseEntity.ok(ApiResponse.ok("查询记录成功", response))
    }

    /**
     * 5. 获取用户所有练习记录
     */
    @Operation(
        summary = "获取我的练习记录",
        description = "获取当前用户的所有练习记录列表"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "获取成功"),
        SwaggerApiResponse(responseCode = "401", description = "会话无效")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @GetMapping("/my-records")
    fun getMyRecords(
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<UserRecordListResponse>> {
        logger.info("获取用户所有练习记录")

        val userId = getUserId(httpRequest)
        val records = exerciseRecordService.findByUserId(userId)
        val response = UserRecordListResponse(buildUserRecordSummaries(records))
        return ResponseEntity.ok(ApiResponse.ok("查询成功", response))
    }

    /**
     * 6. 获取用户练习统计
     */
    @Operation(
        summary = "获取练习统计",
        description = "获取当前用户的练习统计信息"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "获取成功"),
        SwaggerApiResponse(responseCode = "401", description = "会话无效")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @GetMapping("/statistics")
    fun getUserStatistics(
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<UserStatisticsResponse>> {
        logger.info("获取用户练习统计")

        val userId = getUserId(httpRequest)
        val statistics = exerciseRecordService.getUserStatistics(userId)

        val response = UserStatisticsResponse(
            totalRecords = statistics.totalRecords,
            practiceRecords = statistics.practiceRecords,
            testRecords = statistics.testRecords,
            completedRecords = statistics.completedRecords,
            averageScore = statistics.averageScore
        )

        return ResponseEntity.ok(ApiResponse.ok("统计查询成功", response))
    }

    /**
     * 根据用户ID获取已完成的练习记录
     */
    @Operation(
        summary = "根据用户ID获取已完成记录",
        description = "根据指定用户ID查询该用户的所有已完成练习/测试记录"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "获取成功"),
        SwaggerApiResponse(responseCode = "400", description = "用户ID无效")
    ])
    @GetMapping("/user/{userId}/completed")
    fun getUserCompletedRecords(
        @Parameter(description = "用户ID") @PathVariable userId: Long
    ): ResponseEntity<ApiResponse<UserRecordListResponse>> {
        logger.info("获取用户已完成练习记录: userId={}", userId)

        return try {
            // 获取用户所有记录
            val allRecords = exerciseRecordService.findByUserId(userId)
            val completedRecords = allRecords.filter { it.isCompleted() }
            val response = UserRecordListResponse(buildUserRecordSummaries(completedRecords))
            ResponseEntity.ok(ApiResponse.ok("获取用户已完成记录成功", response))
            
        } catch (e: Exception) {
            logger.error("获取用户已完成记录失败", e)
            ResponseEntity.internalServerError().body(
                ApiResponse.error("获取用户已完成记录失败: ${e.message}")
            )
        }
    }

    /**
     * 7. 重置练习记录
     */
    @Operation(
        summary = "重置练习记录",
        description = "将练习记录重置为初始状态，清空所有进度和评分"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "重置成功"),
        SwaggerApiResponse(responseCode = "403", description = "无权访问"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @PostMapping("/{recordId}/reset")
    fun resetExerciseRecord(
        @Parameter(description = "练习记录ID") @PathVariable recordId: String,
        @Parameter(hidden = true) httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseRecordDetailResponse>> {
        return try {
            // 直接重置记录，不做严格权限验证
            // 学生可以重置自己的记录，教师可以重置任何学生的记录
            val resetRecord = exerciseRecordService.resetRecord(recordId)
                ?: return ResponseEntity.badRequest()
                    .body(ApiResponse.error("记录不存在或重置失败"))
            
            val response = buildDetailResponse(resetRecord)
            ResponseEntity.ok(ApiResponse.ok("记录重置成功", response))
            
        } catch (e: Exception) {
            logger.error("重置练习记录失败", e)
            ResponseEntity.status(500)
                .body(ApiResponse.error("重置失败: ${e.message}"))
        }
    }

    /**
     * 8. 删除练习记录（仅练习模式）
     */
    @Operation(
        summary = "删除练习记录",
        description = "删除指定的练习记录（仅练习模式，测试记录不可删除）"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "删除成功"),
        SwaggerApiResponse(responseCode = "400", description = "测试记录不可删除"),
        SwaggerApiResponse(responseCode = "403", description = "无权访问"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @DeleteMapping("/{recordId}")
    fun deleteExerciseRecord(
        @PathVariable recordId: String,
        httpRequest: HttpServletRequest
    ): ResponseEntity<ApiResponse<Nothing>> {
        logger.info("删除练习记录: recordId={}", recordId)

        val userId = getUserId(httpRequest)
        val record = exerciseRecordService.findById(recordId)
            ?: return ResponseEntity.notFound().build()

        // 验证记录所有权
        if (record.userId != userId) {
            return ResponseEntity.status(403).body(
                ApiResponse.error("无权删除此练习记录")
            )
        }

        // 只允许删除练习记录
        if (record.mode != ExerciseMode.PRACTICE) {
            return ResponseEntity.badRequest().body(
                ApiResponse.error("只能删除练习记录，测试记录不可删除")
            )
        }

        val deleted = exerciseRecordService.delete(recordId)
        return if (deleted) {
            ResponseEntity.ok(ApiResponse.ok("练习记录删除成功"))
        } else {
            ResponseEntity.internalServerError().body(
                ApiResponse.error("删除失败")
            )
        }
    }

    /**
     * 获取当前用户ID
     */
    private fun getUserId(request: HttpServletRequest): Long {
        val sessionKey = request.getHeader("Authorization")?.removePrefix("Bearer ")
            ?: throw IllegalStateException("缺少会话令牌")

        val session = userSessionService.validateSession(sessionKey)
            ?: throw IllegalStateException("会话无效或已过期，请重新登录")

        // 更新会话访问时间
        userSessionService.updateSessionAccess(sessionKey)

        return session.userId
    }

    /**
     * 验证练习记录的权限和模式，返回ResponseEntity或记录 - 消除重复代码
     */
    private fun validatePracticeRecordAccessWithResponse(
        recordId: String,
        userId: Long
    ): Pair<ExerciseRecord?, ResponseEntity<ApiResponse<ExerciseProgressResponse>>?> {
        val record = exerciseRecordService.findById(recordId)
            ?: return null to ResponseEntity.notFound().build()

        if (record.userId != userId) {
            return null to ResponseEntity.status(403).body(
                ApiResponse.error("无权访问此练习记录")
            )
        }

        if (record.mode != ExerciseMode.PRACTICE) {
            return null to ResponseEntity.badRequest().body(
                ApiResponse.error("只有练习模式支持分阶段更新")
            )
        }

        return record to null
    }

    /**
     * 构建进度响应对象 - 消除重复代码
     */
    private fun buildProgressResponse(record: ExerciseRecord): ExerciseProgressResponse {
        return ExerciseProgressResponse(
            recordId = record.id,
            paperId = record.paperId,
            mode = record.mode,
            status = record.status,
            currentSection = record.currentStage,
            currentQuestionIndex = record.currentQuestionIndex,
            progressPercentage = record.getProgressPercentage(),
            totalScore = record.totalScore,
            createdAt = record.createdAt,
            updatedAt = record.updatedAt,
            completedAt = record.completedAt
        )
    }

    /**
     * 构建详细响应对象
     */
    private fun buildDetailResponse(record: ExerciseRecord): ExerciseRecordDetailResponse {
        val readingDetails = record.parseReadingScoreDetails()
        val readingDto = readingDetails?.let {
            ReadingScoreDetailsDto(
                suggestedScore = it.suggestedScore,
                pronAccuracy = it.accuracy,
                pronFluency = it.fluency,
                pronCompletion = it.completeness,
                wordMatches = it.wordMatches?.let { wm ->
                    WordMatchesDto(
                        wordAnalysis = wm.wordAnalysis.map { wa ->
                            WordAnalysisDto(
                                index = wa.index,
                                word = wa.word,
                                referenceWord = wa.referenceWord,
                                matchTag = wa.matchTag,
                                matchStatus = wa.matchStatus,
                                isCorrect = wa.isCorrect
                            )
                        },
                        statistics = WordStatisticsDto(
                            total = wm.statistics.total,
                            correct = wm.statistics.correct,
                            wrong = wm.statistics.wrong,
                            missing = wm.statistics.missing
                        ),
                        accuracy = wm.accuracy
                    )
                }
            )
        }

        return ExerciseRecordDetailResponse(
            id = record.id,
            userId = record.userId,
            paperId = record.paperId,
            mode = record.mode,
            status = record.status,
            currentSection = record.currentStage,
            progressPercentage = record.getProgressPercentage(),
            currentQuestionIndex = record.currentQuestionIndex,
            readingAnswer = record.readingAnswer?.let { ra ->
                ReadingAnswerDto(
                    completed = ra.completed,
                    audioFileId = ra.audioFileId,
                    scoreDetails = readingDto,
                    attemptTime = ra.attemptTime
                )
            },
            listeningAnswers = record.listeningAnswers.map { a ->
                QuestionAnswerDto(
                    number = a.number,
                    completed = a.completed,
                    audioFileId = a.audioFileId,
                    score = a.score,
                    attemptTime = a.attemptTime
                )
            },
            dialogueAnswers = record.dialogueAnswers.map { a ->
                QuestionAnswerDto(
                    number = a.number,
                    completed = a.completed,
                    audioFileId = a.audioFileId,
                    score = a.score,
                    attemptTime = a.attemptTime
                )
            },
            expressionAnswer = record.expressionAnswer?.let { ea ->
                ExpressionAnswerDto(
                    completed = ea.completed,
                    audioFileId = ea.audioFileId,
                    score = ea.score,
                    scoreDetails = ea.scoreDetails?.let { es ->
                        ExpressionScoreDetailsDto(
                            suggestedScore = es.suggestedScore ?: BigDecimal.ZERO,
                            pronAccuracy = es.accuracy ?: BigDecimal.ZERO,
                            pronFluency = es.fluency ?: BigDecimal.ZERO,
                            pronCompletion = es.completeness ?: BigDecimal.ZERO
                        )
                    },
                    attemptTime = ea.attemptTime
                )
            },
            totalScore = record.totalScore,
            createdAt = record.createdAt,
            updatedAt = record.updatedAt,
            completedAt = record.completedAt
        )
    }

    /**
     * 构建用户练习记录概要列表（去重公共逻辑）
     */
    private fun buildUserRecordSummaries(records: List<ExerciseRecord>): List<UserRecordSummaryDto> {
        return records.map { record ->
            val paperTitle = examPaperService.getExamPaperById(record.paperId)?.title ?: "试卷${record.paperId}"
            UserRecordSummaryDto(
                recordId = record.id,
                paperId = record.paperId,
                paperTitle = paperTitle,
                mode = record.mode,
                progressPercentage = record.getProgressPercentage(),
                totalScore = record.totalScore,
                isCompleted = record.isCompleted(),
                createdAt = record.createdAt,
                completedAt = record.completedAt
            )
        }
    }

    /**
     * 教师专用 - 获取学生的练习记录列表
     */
    @Operation(
        summary = "获取学生练习记录",
        description = "教师查看指定学生的练习记录列表"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "获取成功"),
        SwaggerApiResponse(responseCode = "403", description = "权限不足"),
        SwaggerApiResponse(responseCode = "404", description = "学生不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @GetMapping("/teacher/student/{studentId}/records")
    fun getTeacherStudentRecords(
        @Parameter(description = "学生用户ID") @PathVariable studentId: Long,
        request: HttpServletRequest
    ): ResponseEntity<ApiResponse<UserRecordListResponse>> {
        logger.info("教师查询学生练习记录: studentId={}", studentId)

        // 验证教师身份
        val teacher = teacherPermissionHelper.validateTeacher(request)
            ?: return ResponseEntity.status(403).body(
                ApiResponse.error("权限不足，只有教师可以访问")
            )

        // 验证教师是否可以访问该学生
        if (!teacherPermissionHelper.canAccessStudent(teacher, studentId)) {
            return ResponseEntity.status(403).body(
                ApiResponse.error("权限不足，无法访问该学生的练习记录")
            )
        }

        return try {
            val records = exerciseRecordService.findByUserId(studentId)
            val response = UserRecordListResponse(buildUserRecordSummaries(records))
            ResponseEntity.ok(ApiResponse.ok("获取学生练习记录成功", response))
        } catch (e: Exception) {
            logger.error("获取学生练习记录失败", e)
            ResponseEntity.internalServerError().body(
                ApiResponse.error("获取学生练习记录失败")
            )
        }
    }

    /**
     * 教师专用 - 查看学生的练习记录详情
     */
    @Operation(
        summary = "获取学生练习记录详情",
        description = "教师查看指定学生的练习记录详细信息"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "获取成功"),
        SwaggerApiResponse(responseCode = "403", description = "权限不足"),
        SwaggerApiResponse(responseCode = "404", description = "记录不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @GetMapping("/teacher/record/{recordId}")
    fun getTeacherStudentRecord(
        @Parameter(description = "练习记录ID") @PathVariable recordId: String,
        request: HttpServletRequest
    ): ResponseEntity<ApiResponse<ExerciseRecordDetailResponse>> {
        logger.info("教师查询学生练习记录详情: recordId={}", recordId)

        // 验证教师身份
        val teacher = teacherPermissionHelper.validateTeacher(request)
            ?: return ResponseEntity.status(403).body(
                ApiResponse.error("权限不足，只有教师可以访问")
            )

        return try {
            val record = exerciseRecordService.findById(recordId)
                ?: return ResponseEntity.status(404).body(
                    ApiResponse.error("练习记录不存在")
                )

            // 验证教师是否可以访问该学生的记录
            if (!teacherPermissionHelper.canAccessStudentRecord(teacher, record.userId, record.userId)) {
                return ResponseEntity.status(403).body(
                    ApiResponse.error("权限不足，无法访问该练习记录")
                )
            }

            val response = buildDetailResponse(record)
            ResponseEntity.ok(ApiResponse.ok("获取练习记录详情成功", response))
        } catch (e: Exception) {
            logger.error("获取练习记录详情失败", e)
            ResponseEntity.internalServerError().body(
                ApiResponse.error("获取练习记录详情失败")
            )
        }
    }

    /**
     * 教师专用 - 获取班级练习记录统计
     */
    @Operation(
        summary = "获取班级练习统计",
        description = "教师查看指定班级的练习记录统计信息"
    )
    @ApiResponses(value = [
        SwaggerApiResponse(responseCode = "200", description = "获取成功"),
        SwaggerApiResponse(responseCode = "403", description = "权限不足"),
        SwaggerApiResponse(responseCode = "404", description = "班级不存在")
    ])
    @SecurityRequirement(name = "BearerAuth")
    @GetMapping("/teacher/class/{classId}/statistics")
    fun getTeacherClassStatistics(
        @Parameter(description = "班级ID") @PathVariable classId: Long,
        request: HttpServletRequest
    ): ResponseEntity<ApiResponse<Map<String, Any>>> {
        logger.info("教师查询班级练习统计: classId={}", classId)

        // 验证教师身份
        val teacher = teacherPermissionHelper.validateTeacher(request)
            ?: return ResponseEntity.status(403).body(
                ApiResponse.error("权限不足，只有教师可以访问")
            )

        // 验证教师是否可以访问该班级
        if (!teacherPermissionHelper.canAccessClass(teacher, classId)) {
            return ResponseEntity.status(403).body(
                ApiResponse.error("权限不足，无法访问该班级")
            )
        }

        return try {
            val classStatistics = exerciseRecordService.getClassStatistics(classId)

            val response: Map<String, Any> = mapOf(
                "classId" to classId,
                "totalStudents" to classStatistics.totalStudents,
                "activeStudents" to classStatistics.activeStudents,
                "totalRecords" to classStatistics.totalRecords,
                "completedRecords" to classStatistics.completedRecords,
                "averageScore" to (classStatistics.averageScore ?: 0),
                "practiceRecords" to classStatistics.practiceRecords,
                "testRecords" to classStatistics.testRecords
            )

            ResponseEntity.ok(ApiResponse.ok("获取班级练习统计成功", response))
        } catch (e: Exception) {
            logger.error("获取班级练习统计失败", e)
            ResponseEntity.internalServerError().body(
                ApiResponse.error("获取班级练习统计失败")
            )
        }
    }
}
